/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.way.gesture;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.gesture.Gesture;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.way.floatwindow.FloatWindowService;
import com.way.util.AppUtil;
import com.way.util.GestureLibraryManager;
import com.way.widget.SlidingLeftViewGroup;

public class GestureBuilderActivity extends ListActivity {
	private static final int STATUS_SUCCESS = 0;
	private static final int STATUS_CANCELLED = 1;
	private static final int STATUS_NO_STORAGE = 2;
	private static final int STATUS_NOT_LOADED = 3;

	private FragmentHelp mHelp;
	// private File mGestureLibraryFile;

	private final Comparator<NamedGesture> mSorter = new Comparator<NamedGesture>() {
		public int compare(NamedGesture object1, NamedGesture object2) {
			return object1.name.compareTo(object2.name);
		}
	};

	private static GestureLibraryManager mGestureLibraryManager;

	private GesturesAdapter mAdapter;
	private GesturesLoadTask mTask;
	private TextView mEmpty;

	private View mRootView;
	private View mDisableView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// android.os.TopwiseProp.getDefaultSettingBoolean("haha");

		setContentView(R.layout.gestures_list);
		AppUtil.transWindows(this,
				getResources().getColor(R.color.material_teal));
		// getActionBar().setDisplayHomeAsUpEnabled(true);
		// mGestureLibraryFile = new File(getFilesDir(),
		// MainActivity.GESTURE_FILE);
		mAdapter = new GesturesAdapter(this);
		setListAdapter(mAdapter);

		mEmpty = (TextView) findViewById(android.R.id.empty);
		mDisableView = findViewById(R.id.disable_textview);
		mRootView = findViewById(R.id.gesture_list_rootview);
		addActionBarSwitch();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.help, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == android.R.id.home) {
			startActivity(new Intent(GestureBuilderActivity.this,
					MainActivity.class));
			return true;
		} else if (item.getItemId() == R.id.menu_help) {
			if (mHelp != null)
				mHelp.show(getFragmentManager(), this, false);
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	private void addActionBarSwitch() {
		Switch actionBarSwitch = (Switch) LayoutInflater.from(this).inflate(
				R.layout.switch_widget, null);
		final int padding = getResources().getDimensionPixelSize(
				R.dimen.action_bar_switch_padding);
		actionBarSwitch.setPadding(0, 0, 0, 0);
		getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
				ActionBar.DISPLAY_SHOW_CUSTOM);
		getActionBar().setCustomView(
				actionBarSwitch,
				new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
						ActionBar.LayoutParams.WRAP_CONTENT,
						Gravity.CENTER_VERTICAL | Gravity.RIGHT));
		// boolean defaultValue = PreferenceManager.getDefaultSharedPreferences(
		// this).getBoolean("isClose", true);
		boolean defaultValue = Settings.System.getInt(getContentResolver(),
				"isGestureClose", 0) == 1 ? true : false;
		if(defaultValue)
			startService(new Intent(this, FloatWindowService.class));
		actionBarSwitch.setChecked(defaultValue);
		actionBarSwitch.setOnCheckedChangeListener(mOnCheckedChangeListener);
		updateUi(defaultValue);
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		final NamedGesture gesture = (NamedGesture) getListAdapter().getItem(
				position);
		Intent intent = new Intent(this, EditGestureActivity.class);
		intent.putExtra("gestureName", gesture.name);
		// intent.putExtra("edit_gesture", gesture.gesture);
		startActivity(intent);
	}

	@Override
	protected void onResume() {
		super.onResume();
		if (mGestureLibraryManager == null) {
			mGestureLibraryManager = GestureLibraryManager.getInstance(this);
		}
		loadGestures();
		if (this.mHelp == null) {
			this.mHelp = new FragmentHelp();
			this.mHelp.show(getFragmentManager(), this, true);
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		if (mTask != null
				&& mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
			mTask.cancel(true);
			mTask = null;
		}
		if ((this.mHelp != null) && (this.mHelp.isVisible()))
			this.mHelp.dismiss();
	}

	private OnCheckedChangeListener mOnCheckedChangeListener = new OnCheckedChangeListener() {

		@Override
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			Log.i("liweiping", "isChecked = " + isChecked);
			Settings.System.putInt(getContentResolver(), "isGestureClose",
					isChecked ? 1 : 0);
			if (isChecked)
				startService(new Intent(GestureBuilderActivity.this,
						FloatWindowService.class));
			else
				stopService(new Intent(GestureBuilderActivity.this,
						FloatWindowService.class));
			// PreferenceManager
			// .getDefaultSharedPreferences(GestureBuilderActivity.this)
			// .edit().putBoolean("isClose", isChecked).commit();
			updateUi(isChecked);
		}
	};

	protected void updateUi(boolean isChecked) {
		if (isChecked) {
			mDisableView.setVisibility(View.GONE);
			mRootView.setVisibility(View.VISIBLE);
		} else {
			mDisableView.setVisibility(View.VISIBLE);
			mRootView.setVisibility(View.GONE);
		}
	}

	@SuppressWarnings({ "UnusedDeclaration" })
	public void reloadGestures(View v) {
		loadGestures();
	}

	@SuppressWarnings({ "UnusedDeclaration" })
	public void addGesture(View v) {
		Intent intent = new Intent(this, SelectTaskActivity.class);
		startActivity(intent);
	}

	private void loadGestures() {
		if (mTask != null
				&& mTask.getStatus() != GesturesLoadTask.Status.FINISHED) {
			mTask.cancel(true);
		}
		mTask = (GesturesLoadTask) new GesturesLoadTask().execute();
	}

	private void checkForEmpty() {
		if (mAdapter.getCount() == 0) {
			mEmpty.setText(R.string.gestures_empty);
		}
	}

	private void changeGestureName() {
		final String name = "";
		if (!TextUtils.isEmpty(name)) {
			final NamedGesture renameGesture = null;
			final GesturesAdapter adapter = mAdapter;
			final int count = adapter.getCount();

			// Simple linear search, there should not be enough items to warrant
			// a more sophisticated search
			for (int i = 0; i < count; i++) {
				final NamedGesture gesture = adapter.getItem(i);
				if (gesture.gesture.getID() == renameGesture.gesture.getID()) {
					mGestureLibraryManager.removeGesture(gesture.name);
					gesture.name = "";
					mGestureLibraryManager.updateGesture(gesture.name,
							gesture.gesture);
					break;
				}
			}

			adapter.notifyDataSetChanged();
		}
	}

	private void deleteGesture(NamedGesture gesture) {
		mGestureLibraryManager.removeGesture(gesture.name);

		final GesturesAdapter adapter = mAdapter;
		adapter.setNotifyOnChange(false);
		adapter.remove(gesture);
		adapter.sort(mSorter);
		checkForEmpty();
		adapter.notifyDataSetChanged();

		Toast.makeText(this, R.string.gestures_delete_success,
				Toast.LENGTH_SHORT).show();
	}

	private class GesturesLoadTask extends
			AsyncTask<Void, NamedGesture, Integer> {
		private int mThumbnailSize;
		private int mThumbnailInset;
		private int mPathColor;

		@Override
		protected void onPreExecute() {
			super.onPreExecute();

			final Resources resources = getResources();
			// mPathColor = resources.getColor(R.color.gesture_color);
			mPathColor = Color.BLACK;
			mThumbnailInset = (int) resources
					.getDimension(R.dimen.gesture_thumbnail_inset);
			mThumbnailSize = (int) resources
					.getDimension(R.dimen.gesture_thumbnail_size);

			findViewById(R.id.addButton).setEnabled(false);
			findViewById(R.id.reloadButton).setEnabled(false);

			mAdapter.setNotifyOnChange(false);
			mAdapter.clear();
		}

		@Override
		protected Integer doInBackground(Void... params) {
			if (isCancelled())
				return STATUS_CANCELLED;

			// final GestureLibrary store = mGestureLibraryManager;

			if (mGestureLibraryManager.load()) {
				for (String name : mGestureLibraryManager.getGestureEntries()) {
					if (isCancelled())
						break;

					for (Gesture gesture : mGestureLibraryManager
							.getGestures(name)) {
						final Bitmap bitmap = gesture.toBitmap(mThumbnailSize,
								mThumbnailSize, mThumbnailInset, mPathColor);
						final NamedGesture namedGesture = new NamedGesture();
						namedGesture.gesture = gesture;
						namedGesture.name = name;

						mAdapter.addBitmap(namedGesture.gesture.getID(), bitmap);
						publishProgress(namedGesture);
					}
				}

				return STATUS_SUCCESS;
			}

			return STATUS_NOT_LOADED;
		}

		@Override
		protected void onProgressUpdate(NamedGesture... values) {
			super.onProgressUpdate(values);

			final GesturesAdapter adapter = mAdapter;
			adapter.setNotifyOnChange(false);

			for (NamedGesture gesture : values) {
				adapter.add(gesture);
			}

			adapter.sort(mSorter);
			adapter.notifyDataSetChanged();
		}

		@Override
		protected void onPostExecute(Integer result) {
			super.onPostExecute(result);

			if (result == STATUS_NO_STORAGE) {
				getListView().setVisibility(View.GONE);
				mEmpty.setVisibility(View.VISIBLE);
				mEmpty.setText(R.string.gestures_error_loading);
			} else {
				findViewById(R.id.addButton).setEnabled(true);
				findViewById(R.id.reloadButton).setEnabled(true);
				checkForEmpty();
			}
		}
	}

	static class NamedGesture {
		String name;
		Gesture gesture;
	}

	private class GesturesAdapter extends ArrayAdapter<NamedGesture> implements
			SlidingLeftViewGroup.OnSlideListener {
		private final LayoutInflater mInflater;
		private SlidingLeftViewGroup mSlidingItem;
		private final Map<Long, Drawable> mThumbnails = Collections
				.synchronizedMap(new HashMap<Long, Drawable>());

		public GesturesAdapter(Context context) {
			super(context, 0);
			mInflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		void addBitmap(Long id, Bitmap bitmap) {
			mThumbnails.put(
					id,
					new BitmapDrawable(GestureBuilderActivity.this
							.getResources(), bitmap));
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				convertView = mInflater.inflate(R.layout.multiview, parent,
						false);
				holder = new ViewHolder();

				holder.mListItem = (SlidingLeftViewGroup) convertView
						.findViewById(R.id.mymultiViewGroup);
				holder.mLL = (LinearLayout) convertView
						.findViewById(R.id.item_ll);
				holder.mName = (TextView) convertView.findViewById(R.id.name);
				holder.mDel = (Button) convertView
						.findViewById(R.id.gestures_delete);
				holder.mTop = (Button) convertView
						.findViewById(R.id.gestures_edit);
				convertView.setTag(holder);
			}
			holder = (ViewHolder) convertView.getTag();
			setupHolder(holder, convertView, position);

			return convertView;
		}

		private void setupHolder(ViewHolder holder, View view, int position) {
			final NamedGesture gesture = getItem(position);
			holder.mName.setTag(gesture);
			setName(holder.mName, gesture.name);
			holder.mName.setCompoundDrawablesWithIntrinsicBounds(
					mThumbnails.get(gesture.gesture.getID()), null, null, null);
			holder.mPos = position;
			holder.mLL.setTag(holder);

			holder.mDel.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View view) {
					deleteGesture(gesture);
				}
			});
			holder.mTop.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View arg0) {
					Intent intent = new Intent(GestureBuilderActivity.this,
							EditGestureActivity.class);
					intent.putExtra("gestureName", gesture.name);
					startActivity(intent);
				}
			});

			holder.mLL.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View view) {
					Intent intent = new Intent(GestureBuilderActivity.this,
							EditGestureActivity.class);
					intent.putExtra("gestureName", gesture.name);
					startActivity(intent);
				}
			});

			holder.mListItem.setSlidingListener(this);
		}

		private void setName(TextView label, String name) {
			if (!name.contains(","))
				return;
			String[] names = name.split(",");
			int command = Integer.valueOf(names[0]);
			switch (command) {
			case SelectTaskActivity.APP_COMMAND:
				label.setText(String.format(
						getResources().getString(R.string.app_prex), names[3]));
				break;
			case SelectTaskActivity.DIAL_COMMAND:
				if (names.length > 1)
					label.setText(String.format(
							getResources().getString(R.string.dial_prex),
							names[2]));
				else
					label.setText(String.format(
							getResources().getString(R.string.dial_prex),
							names[1]));
				break;
			case SelectTaskActivity.MMS_COMMAND:
				if (names.length > 1)
					label.setText(String.format(
							getResources().getString(R.string.mms_prex),
							names[2]));
				else
					label.setText(String.format(
							getResources().getString(R.string.mms_prex),
							names[1]));
				break;
			default:
				break;
			}
		}

		@Override
		public void onSlideToLeft(SlidingLeftViewGroup item) {
			mSlidingItem = item;
		}

		@Override
		public void onSlideBack() {
			mSlidingItem = null;
		}

		@Override
		public void onSlidingStart(SlidingLeftViewGroup item) {
			if (mSlidingItem != null && item != null && mSlidingItem != item) {
				mSlidingItem.MoveBack(false);
			}
		}

		private class ViewHolder {
			private int mPos;
			private SlidingLeftViewGroup mListItem;
			private LinearLayout mLL;
			private TextView mName;
			private Button mDel;
			private Button mTop;
		}

		public void deleteGesture(final NamedGesture gesture) {
			AlertDialog.Builder builder = new AlertDialog.Builder(
					GestureBuilderActivity.this);
			builder.setTitle(R.string.gestures_delete)
					.setMessage(R.string.gestures_delete_toast)
					.setNegativeButton(R.string.cancel_action, null)
					.setPositiveButton(R.string.rename_action,
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									GestureBuilderActivity.this
											.deleteGesture(gesture);
									if (mSlidingItem != null) {
										mSlidingItem.MoveBack(false);
									}
								}
							}).create().show();
		}
	}

}
